package com.xjtu.chapter08.thread.producer_consumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author yjq
 * @version 1.0
 * @date 2021/8/31 21:31
 */
public class Storage2 {
    Product[] products = new Product[10];
    static int top = 0;

    Lock myLock = new ReentrantLock();//定义一个lock
    Condition full = myLock.newCondition();//定义一个full的阻塞条件
    Condition empty = myLock.newCondition();//定义一个empty的阻塞条件

    //生产者往仓库中放入产品
    public void push(Product product) {
        myLock.lock();//获取锁
        try {
            while (top == products.length) {
                System.out.println("storage is full, producer is waiting");
                full.await();//仓库已满，producer在full条件下被阻塞
            }
            //把产品放进仓库
            products[top++] = product;
            System.out.println(Thread.currentThread().getName() + " creates " + product);
            empty.signal();//唤醒在empty条件下等待的consumer
        } catch (InterruptedException e) {
            System.out.println("producer failed to wait");
            e.printStackTrace();
        } finally {
            myLock.unlock();//释放锁
        }
    }

    //消费者从仓库中取出产品
    public void pop() {
        myLock.lock();//获得锁
        try {
            while (top == 0) {
                System.out.println("storage is empty,consumer is waiting");
                empty.await();//仓库空，consumer在empty的条件下被阻塞
            }
            //从仓库中取产品
            --top;
            Product p = new Product(products[top].id, products[top].name);
            products[top] = null;
            System.out.println(Thread.currentThread().getName() + " buy " + p);
            full.signal();
        } catch (InterruptedException e) {
            System.out.println("consumer failed to wait");
            e.printStackTrace();
        } finally {
            myLock.unlock();//释放锁
        }
    }
}
